/**
 * 处理请求
 */
const handleRequest = {
  his(config, vm) {
    // 可使用async await 做异步操作
    // 初始化请求拦截器时，会执行此方法，此时data为undefined，赋予默认{}
    config.data = config.data || {};
    // 根据custom参数中配置的是否需要token，添加对应的请求头
    if (config?.custom?.auth) {
      // 可以在此通过vm引用vuex中的变量，具体值在vm.$store.state中
      config.header.token = vm.vuexToken;
    }
    return config;
  },

  qiyuesuo(config, vm) {
    // 可使用async await 做异步操作
    // 初始化请求拦截器时，会执行此方法，此时data为undefined，赋予默认{}
    config.data = config.data || {};
    // 根据custom参数中配置的是否需要token，添加对应的请求头
    if (config?.custom?.auth) {
      // 可以在此通过vm引用vuex中的变量，具体值在vm.$store.state中
      config.header.token = vm.vuexToken;
    }
    config.header['x-qys-timestamp'] = '1662619188425';
    config.header['x-qys-accesstoken'] = 'crsZ2sY4Rr';
    config.header['x-qys-signature'] = 'cbd50ad3732e9c87a6c407f1656769ac';
    return config;
  },
};

/**
 * 处理响应
 */
const handleResponse = {
  his(response) {
    const { data } = response;
    const custom = response.config?.custom;
    if (data.errCode !== 0) {
      // 如果没有显式定义custom的toast参数为false的话，默认对报错进行toast弹出提示
      if (custom.toast !== false) {
        uni.$u.toast(data.errMsg);
      }

      // 如果需要catch返回，则进行reject
      if (custom?.catch) {
        return Promise.reject(data);
      }
      // 否则返回一个pending中的promise，请求不会进入catch中
      return new Promise(() => {});
    }
    return data;
  },

  qiyuesuo(response) {
    const { data } = response;
    const custom = response.config?.custom;
    if (data.code !== 0) {
      // 如果没有显式定义custom的toast参数为false的话，默认对报错进行toast弹出提示
      if (custom.toast !== false) {
        uni.$u.toast(data.message);
      }

      // 如果需要catch返回，则进行reject
      if (custom?.catch) {
        return Promise.reject(data);
      }
      // 否则返回一个pending中的promise，请求不会进入catch中
      return new Promise(() => {});
    }
    return data;
  },
};

// 此vm参数为页面的实例，可以通过它引用vuex中的变量
module.exports = (vm) => {
  // 初始化请求配置
  uni.$u.http.setConfig((config) => {
    /* config 为默认全局配置 */
    config.baseURL = '/api'; /* 根域名 */
    return config;
  });

  // 请求拦截
  uni.$u.http.interceptors.request.use(
    (config) => {
      const timeoutID = setTimeout(() => {
        uni.showLoading({ title: '请等待...' });
      }, 800);
      config.custom.timeoutID = timeoutID;
      const key = config.url.split('/')[1];
      return handleRequest[key](config, vm);
    },
    (config) => {
      // 可使用async await 做异步操作
      Promise.reject(config);
    },
  );

  // 响应拦截
  uni.$u.http.interceptors.response.use(
    // 这里是响应成功之后的处理
    (response) => {
      clearTimeout(response.config.custom.timeoutID);
      uni.hideLoading();
      const {
        config: { url },
      } = response;
      const key = url.split('/')[1];
      return handleResponse[key](response);
    },

    // 这里是响应失败之后的处理
    (response) => {
      clearTimeout(response.config.custom.timeoutID);
      uni.hideLoading();

      const { errMsg, data } = response;

      // 对于请求不成功的错误，做提示
      if (errMsg !== 'request:ok') {
        const wrongTable = {
          'request:fail':
            '操作失败，请尝试重新操作。可能是网络不通、服务不可用',
          'request:fail timeout': '操作超时，请检查网络，再尝试重新操作',
        };

        if (wrongTable[errMsg]) {
          uni.$u.toast(wrongTable[errMsg]);
        } else {
          uni.$u.toast(errMsg);
        }
        return Promise.reject(errMsg);
      }

      // 如果data不是字符串类型的，建议细化处理，让提示更加人性化
      if (typeof data === 'string') {
        uni.$u.toast(data);
      } else {
        uni.$u.toast(JSON.stringify(data));
      }

      return Promise.reject(response);
    },
  );
};
